/**
 * main.c - 钩子框架主入口点 (类eBPF架构)
 *
 * 这个文件包含库的自动初始化和清理函数
 * 在被程序动态加载时自动调用
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#include <dirent.h>

#include "../include/hook_framework.h"

/* 插件目录 */
static const char* DEFAULT_PLUGIN_DIR = "./plugins";

/**
 * 扫描并加载插件
 * 
 * 扫描指定目录中的所有.so文件并尝试加载它们
 */
static void load_plugins_from_directory(const char* dir_path) {
    DIR* dir;
    struct dirent* entry;
    
    dir = opendir(dir_path);
    if (!dir) {
        log_message(LOG_WARN, "无法打开插件目录: %s", dir_path);
        return;
    }
    
    log_message(LOG_INFO, "正在扫描插件目录: %s", dir_path);
    
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_REG || entry->d_type == DT_UNKNOWN) {
            const char* ext = strrchr(entry->d_name, '.');
            if (ext && strcmp(ext, ".so") == 0) {
                char plugin_path[512];
                snprintf(plugin_path, sizeof(plugin_path), "%s/%s", dir_path, entry->d_name);
                
                // 尝试加载插件
                if (load_plugin(plugin_path)) {
                    log_message(LOG_INFO, "已加载插件: %s", entry->d_name);
                } else {
                    log_message(LOG_ERROR, "加载插件失败: %s", entry->d_name);
                }
            }
        }
    }
    
    closedir(dir);
}

/**
 * 初始化函数 - 自动调用
 * 
 * 当库被加载时自动调用
 * 负责初始化钩子框架和加载插件
 */
__attribute__((constructor))
static void init(void) {
    // 初始化钩子框架
    if (!init_hook_framework()) {
        return;
    }
    
    // 从环境变量获取插件目录
    const char* plugin_dir = getenv("HOOK_PLUGIN_DIR");
    if (!plugin_dir) {
        plugin_dir = DEFAULT_PLUGIN_DIR;
    }
    
    // 加载插件
    load_plugins_from_directory(plugin_dir);
    
    // 输出版本信息
    log_message(LOG_INFO, "%s 初始化完成", HOOK_FRAMEWORK_NAME);
}

/**
 * 清理函数 - 自动调用
 * 
 * 当库被卸载时自动调用
 * 负责清理钩子框架
 */
__attribute__((destructor))
static void cleanup(void) {
    // 清理钩子框架
    cleanup_hook_framework();
    
    log_message(LOG_INFO, "%s 已清理", HOOK_FRAMEWORK_NAME);
}
